/*
* @Author: z.p
* @Project: Zdotp
* @Date: 2025年01月15日
* @Description: ZyActor的对象池文件
*/
namespace Zdotp.ObjectPool;

public class ObjectPool<T> : ObjectPoolBase where T : ObjectBase, new()
{
    private readonly List<PObject<T>> _pool = new();
    private int _currentSize;
    private uint _maxId;

    private uint GetNewId()
    {
        if (_maxId + 1 == uint.MaxValue / 2)
        {
            _maxId = 0;
        }
        return ++_maxId;
    }
    private readonly Lock _lock = new();

    private int ObjCount => _pool.Count;

    private PObject<T> AddObj()
    {
        var obj = new T { ObjId = GetNewId() };
        var foo = new PObject<T>(obj);
        _pool.Add(foo);
        return foo;
    }
    public T? GetObj(Action<T>? init = null, Action<T>? callback = null)
    {
        T? data = null;
        lock (_lock)
        {
            if (_currentSize <= 0)
            {
                var foo = AddObj();
                data = foo.GetObj(init, callback);
            }
            else
            {
                for (var i = ObjCount - 1; i >= 0; i--)
                {
                    data = _pool[i].GetObj(init, callback);
                    if (data == null) continue;
                    --_currentSize;
                    break;
                }
                // 全部正在使用...
                if (data == null)
                {
                    var foo = AddObj();
                    data = foo.GetObj(init, callback);
                }
            }
            if (ObjectPoolManager.IsLogger)
            {
                GetInfo(InfoType.Get);
            }
        }

        return data;
    }
    
    public void ReleaseObj(T obj)
    {
        lock (_lock)
        {
            for (var i = ObjCount - 1; i >= 0; i--)
            {
                if (_pool[i].ReleaseObj(obj))
                {
                    ++_currentSize;
                    if (ObjectPoolManager.IsLogger)
                    {
                        GetInfo(InfoType.Release);
                    }
                    break;
                }
            }
        }
    }

    public override void ReleaseObj(ObjectBase obj)
    {
        ReleaseObj((T)obj);
    }

    private enum InfoType
    {
        Get,
        Release
    }
    private void GetInfo(InfoType type)
    {
        var cnt = 0;
        foreach (var o in _pool)
        {
            if (!o.IsUsing)
            {
                cnt++;
            }
        }
        Console.WriteLine($"[{typeof(T).Name}, {type}] 当前对象池大小为：{ObjCount}, 当前可用的对象数量为：{_currentSize}, 真正空闲数量 : {cnt}");
    }
}

public abstract class ObjectPoolBase
{
    public IPoolConfig.PoolType PoolType { get; private set; }

    public ObjectPoolBase Build(IPoolConfig.PoolType poolType)
    {
        PoolType = poolType;
        return this;
    }

    public abstract void ReleaseObj(ObjectBase obj);
}